package com.flyxiaozhu.erp.admin.configurations;

import com.flyxiaozhu.erp.admin.authorize.AdminUserDetails;
import com.flyxiaozhu.erp.admin.authorize.AdminUserDetailsService;
import com.flyxiaozhu.erp.admin.authorize.AuthorizeHelper;
import com.flyxiaozhu.erp.core.libs.ErrorCode;
import com.flyxiaozhu.erp.core.libs.JSONResult;
import com.flyxiaozhu.erp.core.libs.RenderUtils;
import com.flyxiaozhu.erp.core.repositories.AdminUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.DigestUtils;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    AdminUserRepository adminUserRepository;

    @Bean
    UserDetailsService customUserDetailService() {
        return new AdminUserDetailsService();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailService())
                .passwordEncoder(new PasswordEncoder() {
                    @Override
                    public String encode(CharSequence charSequence) {
                        return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
                    }

                    @Override
                    public boolean matches(CharSequence charSequence, String s) {
                        return s.equals(DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()));
                    }
                });
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/", "/home", "/dist/**", "**.ico").permitAll()
                .anyRequest().authenticated()

                .and()
                .formLogin()
                .loginProcessingUrl("/login")
                .permitAll()
                .successHandler((request, response, auth) -> {
                    AdminUserDetails userDetails = (AdminUserDetails) auth.getPrincipal();

                    JSONResult result = new JSONResult()
                            .put("user", userDetails.getAdminUser())
                            .put("permission", AuthorizeHelper.getPermissions(userDetails));

                    RenderUtils.renderJson(response, result);
                })
                .failureHandler((request, response, exception) -> {
                    if (exception instanceof BadCredentialsException) {
                        RenderUtils.renderJson(response, new JSONResult(ErrorCode.BAD_CREDENTIALS, "账号或密码错误"));
                    } else if (exception instanceof DisabledException) {
                        RenderUtils.renderJson(response, new JSONResult(ErrorCode.USER_DISABLED, "此账户已被禁用"));
                    } else {
                        RenderUtils.renderJson(response, new JSONResult(ErrorCode.UNKNOWN, "未知错误"));
                    }
                })

                .and()
                .logout()
                .logoutSuccessHandler((request, response, auth) -> response.sendRedirect("/"))
                .permitAll()

                .and()
                .exceptionHandling()
                .authenticationEntryPoint((request, response, exception) -> {
                    RenderUtils.renderJson(response, new JSONResult(ErrorCode.NOT_LOGIN, "尚未登录"));
                });
    }
}
